#ifndef __DEF_DBKAKEIBO_H__
#define __DEF_DBKAKEIBO_H__

#define ISRANGE(VAL, T1, T2) (((VAL >= T1) && (VAL <= T2)) ? true : false)

#include <wx/wx.h>
#include <wx/dynarray.h>
#include "appconstant.h"

#include <vector>

using namespace std;



typedef enum {
	none_it = -1,
	in_it,
	out_it
} InoutType;
typedef enum {
	eq = 0,
	ne,
	ge,
	le,
	gt,
	lt,
	in_operator,
	notin_operator
} operatorType;
typedef enum {
	db_budget = 0,
	db_total,
	db_expense,
	db_items,
	db_accounts
} dbType;
typedef enum {
	none_mt = -1,
	add_mt,
	mod_mt,
	del_mt,
} modifyType;
const wxString dbname[5] = {
	_T("db_budgets"),_T("db_total"),_T("db_expense"),_T("db_items"),_T("db_accounts")
};
const wxString dboperator[8] = {
	_T("="),_T("!="),_T(">="),_T("<="),_T(">"),_T("<"),_T("in (%s)"),_T("not in (%s)")
};

class DB_base
{
public:
	DB_base(void)
	{
		modflag = none_mt;
	}
	DB_base(const DB_base &db)
	{
		modflag = db.modflag;
	}
	void SetFlag(modifyType mt) { modflag = mt; };
	DB_base &operator=(const DB_base &db)
	{
		if (this == &db) return *this;
		modflag = db.modflag;
		return *this;
	}
	modifyType GetFlag(void) { return modflag; };
protected:
	modifyType modflag;
};

class DB_day: public DB_base
{
public:
	DB_day(void)
	{
		Clear();
	}
	DB_day(const DB_day &day);
	~DB_day(void) {}
	void Clear(void);
	void Copy(DB_day &day)
	{
		SetDate(day.GetDate());
		SetIO(day.GetIO());
		SetId(day.GetId());
		SetExpense(day.GetExpense());
		SetItems(day.GetItems());
		SetHandling(day.GetHandling());
		SetIncome(day.GetIncome());
		SetExpenditure(day.GetExpenditure());
		SetMemo(day.GetMemo());
	}
	DB_day &operator=(const DB_day &day);
	void SetDate(const wxDateTime &dt){db_date = dt;}
	const wxDateTime &GetDate(void){return db_date;}
	void SetIO(InoutType id){iotype = id;}
	InoutType GetIO(void){return iotype;}
	void SetId(int id){db_id = id;}
	int GetId(void){return db_id;}
	void SetExpense(int id){expenseid = id;}
	int GetExpense(void){return expenseid;}
	void SetItems(int id){itemsid = id;}
	int GetItems(void){return itemsid;}
	void SetHandling(int hd){handling = hd;}
	int GetHandling(void){return handling;}
	void SetIncome(int val){db_income = val;}
	int GetIncome(void){return db_income;}
	void SetExpenditure(int val){db_expenditure = val;}
	int GetExpenditure(void){return db_expenditure;}
	void SetMemo(const wxString &str){db_memo = str;}
	const wxString &GetMemo(void){return db_memo;}
	void SetExtra(const wxString &str){db_extra = str;}
	const wxString &GetExtra(void){return db_extra;}
	void SetOldDate(const wxDateTime &dt){olddate = dt;}
	const wxDateTime &GetOldDate(void){return olddate;}
private:
	wxDateTime db_date;
	InoutType iotype;
	int db_id;
	int expenseid;
	int itemsid;
	int handling;
	int db_income;
	int db_expenditure;
	wxString db_memo;
	wxString db_extra;
	wxDateTime olddate;

};
class DB_total: public DB_base
{
public:
	DB_total(void)
	{
		Clear();
	}
	DB_total(const DB_total &db);
	~DB_total(void) {}
	void Clear(void);
	DB_total &operator=(const DB_total &db);

	void SetDate(const wxDateTime &dt){db_date = dt;}
	const wxDateTime &GetDate(void){return db_date;}
	void SetHandling(int hd){handling = hd;}
	int GetHandling(void){return handling;}
	void SetIncome(int val){db_income = val;}
	int GetIncome(void){return db_income;}
	void SetExpenditure(int val){db_expenditure = val;}
	int GetExpenditure(void){return db_expenditure;}
	void SetRemainder(int val){db_value = val;}
	int GetRemainder(void){return db_value;}
private:
	wxDateTime db_date;
	int handling;
	int db_income;
	int db_expenditure;
	int db_value;
};
class DB_expense: public DB_base
{
public:
	DB_expense(void)
	{
		Clear();
	}
	DB_expense(const DB_expense &db);
	~DB_expense(void) {}
	void Clear(void);
	DB_expense &operator=(const DB_expense &db);
	
	void SetId(int id){key = id;}
	int GetId(void){return key;}
	void SetIO(InoutType id){iotype = id;}
	InoutType GetIO(void){return iotype;}
	void SetImage(int id){image = id;}
	int GetImage(void){return image;}
	void SetName(const wxString &str){label = str;}
	const wxString &GetName(void){return label;}
	void SetAccount(bool flg){haveaccount = flg;}
	bool GetAccount(void){return haveaccount;}
private:
	int key;
	InoutType iotype;
	int image;
	wxString label;
	bool haveaccount;
};
class DB_items: public DB_base
{
public:
	DB_items(void)
	{
		Clear();
	}
	~DB_items(void) {}
	void Clear(void)
	{
		key = -1;
		image = -1;
		expenseid = -1;
		label.Clear();
	}
	
	void SetId(int id){key = id;}
	int GetId(void){return key;}
	void SetImage(int id){image = id;}
	int GetImage(void){return image;}
	void SetExpense(int id){expenseid = id;}
	int GetExpense(void){return expenseid;}
	void SetName(const wxString &str){label = str;}
	const wxString &GetName(void){return label;}
private:
	int key;
	int image;
	int expenseid;
	wxString label;
};
class DB_account: public DB_base
{
public:
	DB_account(void)
	{
		Clear();
	}
	~DB_account(void) {}
	void Clear(void)
	{
		key = -1;
		initremain = 0;
		label.Clear();
		oldlabel.Clear();
	}
	
	void SetId(int id){key = id;}
	int GetId(void){return key;}
	void SetRemain(int val){initremain = val;}
	int GetRemain(void){return initremain;}
	void SetName(const wxString &str){label = str;}
	const wxString &GetName(void){return label;}
	void SetOldName(const wxString &str){oldlabel = str;}
	const wxString &GetOldName(void){return oldlabel;}
private:
	int key;
	int initremain;
	wxString label;
	wxString oldlabel;
};
class DB_periodical: public DB_base
{
public:
	DB_periodical(void)
	{
		Clear();
	}
	DB_periodical(const DB_periodical &db):DB_base(db)
	{
		key = db.key;
		date = db.date;
		base = db.base;
		valueonday = db.valueonday;
		memoonday = db.memoonday;
		timing = db.timing;
		timingday = db.timingday;
		caseholiday = db.caseholiday;
	}
	~DB_periodical(void) {}
	void Clear(void)
	{
		key = -1;
		date = wxDateTime::Now();
		base.Clear();
		valueonday = false;
		memoonday = false;
		timing = -1;
		timingday = 0;
		caseholiday = 0;
	}
	void Copy(DB_periodical &db)
	{
		SetId(db.GetId());
		SetBudget(db.GetBudget());
		SetInputValue(db.GetInputValue());
		SetInputMemo(db.GetInputMemo());
		SetTiming(db.GetTiming());
		SetTimingDay(db.GetTimingDay());
		SetHoliday(db.GetHoliday());
	}
	DB_periodical &operator=(const DB_periodical &db)
	{
		if (this == &db) return *this;
		DB_base::operator=(db);
		date = db.date;
		key = db.key;
		base = db.base;
		valueonday = db.valueonday;
		memoonday = db.memoonday;
		timing = db.timing;
		timingday = db.timingday;
		caseholiday = db.caseholiday;
		return *this;
	}
	
	void SetId(int id){key = id;}
	int GetId(void){return key;}
	void SetDate(const wxDateTime &str){date = str;}
	const wxDateTime &GetDate(void){return date;}
	void SetBudget(DB_day &db) { base = db; }
	DB_day &GetBudget(void) { return base; }
	void SetInputValue(bool flg){valueonday = flg;}
	bool GetInputValue(void){return valueonday;}
	void SetInputMemo(bool flg){memoonday = flg;}
	bool GetInputMemo(void){return memoonday;}
	void SetTiming(int val){timing = val;}
	int GetTiming(void){return timing;}
	void SetTimingDay(int val){timingday = val;}
	int GetTimingDay(void){return timingday;}
	void SetHoliday(int val){caseholiday = val;}
	int GetHoliday(void){return caseholiday;}
private:
	int key;
	wxDateTime date;
	DB_day base;
	bool valueonday;
	bool memoonday;
	int timing;
	int timingday;
	int caseholiday;
};
class DB_holiday: public DB_base
{
public:
	DB_holiday(void)
	{
		Clear();
	}
	~DB_holiday(void) {}
	void Clear(void)
	{
		date = wxDateTime::Now();
		name.Clear();
	}
	
	void SetDate(const wxDateTime &str){date = str;}
	const wxDateTime &GetDate(void){return date;}
	void SetName(const wxString &str){name = str;}
	const wxString &GetName(void){return name;}
private:
	wxDateTime date;
	wxString name;
};
class DB_reserved: public DB_base
{
public:
	DB_reserved(void)
	{
		Clear();
	}
	~DB_reserved(void) {}
	void Clear(void)
	{
		key = -1;
		type = 0;
		handling = -1;
		stdate = wxDateTime::Now();
		eddate = wxDateTime::Now();
		value = 0;
	}
	
	void SetId(int id){key = id;}
	int GetId(void){return key;}
	void SetType(int val){type = val;}
	int GetType(void){return type;}
	void SetHandling(int hd){handling = hd;}
	int GetHandling(void){return handling;}
	void SetStartDate(const wxDateTime &str){stdate = str;}
	const wxDateTime &GetStartDate(void){return stdate;}
	void SetEndDate(const wxDateTime &str){eddate = str;}
	const wxDateTime &GetEndDate(void){return eddate;}
	void SetValue(int val){value = val;}
	int GetValue(void){return value;}
private:
	int key;
	int type;
	int handling;
	wxDateTime stdate;
	wxDateTime eddate;
	int value;
		
};
//Declare array of db
WX_DECLARE_OBJARRAY(DB_periodical, DBL_periodical);
WX_DECLARE_OBJARRAY(DB_holiday, DBL_holiday);
WX_DECLARE_OBJARRAY(DB_reserved, DBL_reserved);

class DB_setting: public DB_base
{
public:
	DB_setting(void)
	{
		Clear();
	}
	DB_setting(const DB_setting &db):DB_base(db)
	{
		username = db.username;
		bookname = db.bookname;
		startdate = db.startdate;
		initialremainder = db.initialremainder;
		period = db.period;
		holiday = db.holiday;
		reserved = db.reserved;
		settleday = db.settleday;
		settlelastday = db.settlelastday;
		settlemonth = db.settlemonth;
		currencyunit = db.currencyunit;
		startweekday = db.startweekday;
		iconpath = db.iconpath;
		deffont = db.deffont;
		isencrypt = db.isencrypt;
	}
	~DB_setting(void) {}
	void Clear(bool deep = true)
	{
		startdate = wxDateTime::UNow();
		initialremainder = 0;
		period.Clear();
		settleday = 1;
		settlelastday = false;
		settlemonth = 12;
		username.Clear();
		bookname.Clear();
		if (deep) {
			holiday.Clear();
			currencyunit.Clear();
			startweekday = 0;
			iconpath.Clear();
			isencrypt = false;
		}
	}
	void Copy(DB_setting &db)
	{
		Clear();
		username = db.GetUserNames();
		bookname = db.GetBookName();
		startdate = db.GetStartDate();
		initialremainder = (mon_int)db.GetRemainder();
		period = db.GetPeriodAll();
		holiday = db.GetHolidayAll();
		reserved = db.GetBudgetAll();
		settleday = db.GetSettlingDay();
		settlelastday = db.GetSettlingLastDay();
		settlemonth = db.GetSettlingMonth();
		currencyunit = db.GetCurrencyUnit();
		startweekday = db.GetStartWeekDay();
		iconpath = db.GetIconPath();
		deffont = db.GetFontInfo();
		isencrypt = db.GetEncrypt();
	}
	DB_setting &operator=(const DB_setting &db)
	{
		if (this == &db) return *this;
		DB_base::operator=(db);
		username = db.username;
		bookname = db.bookname;
		startdate = db.startdate;
		initialremainder = db.initialremainder;
		period = db.period;
		holiday = db.holiday;
		reserved = db.reserved;
		settleday = db.settleday;
		settlelastday = db.settlelastday;
		settlemonth = db.settlemonth;
		currencyunit = db.currencyunit;
		startweekday = db.startweekday;
		iconpath = db.iconpath;
		deffont = db.deffont;
		isencrypt = db.isencrypt;
		return *this;
	}
	void SetUserName(const wxString &str){username = str;}
	const wxString &GetUserNames(void){return username;}
	void SetBookName(const wxString &str){bookname = str;}
	const wxString &GetBookName(void){return bookname;}
	void SetStartDate(const wxDateTime &str){startdate = str;}
	const wxDateTime &GetStartDate(void){return startdate;}
	void SetRemainder(int val){initialremainder = val;}
	int GetRemainder(void){return initialremainder;}
	void SetEncrypt(bool flag) { isencrypt = flag; }
	bool GetEncrypt(void) { return isencrypt; }

	DB_periodical &GetPeriod(int index){return period.Item(index);}
	void AddPeriod(DB_periodical &db) { period.Add(db,1); }
	void SetPeriod(int index, DB_periodical &db);
	void SetPeriodAll(DBL_periodical &db) {period = db;}
	void RemovePeriod(int index);
	DBL_periodical &GetPeriodAll(void) { return period; }
	int GetPeriodCount(void) { return (int)period.GetCount(); }
	void ClearPeriod(void) { period.Clear(); }

	DB_holiday &GetHoliday(int index){return holiday.Item(index);}
	void AddHoliday(DB_holiday &db) { holiday.Add(db,1); }
	void SetHoliday(int index, DB_holiday &db);
	void RemoveHoliday(int index);
	DBL_holiday &GetHolidayAll(void) { return holiday; }
	int GetHolidayCount(void) { return (int)holiday.GetCount(); }
	void ClearHoliday(void) { holiday.Clear(); }

	DB_reserved &GetBudget(int index){return reserved.Item(index);}
	void AddBudget(DB_reserved &db) { reserved.Add(db,1); }
	void SetBudget(int index, DB_reserved &db);
	void RemoveBudget(int index);
	DBL_reserved &GetBudgetAll(void) { return reserved; }
	int GetBudgetCount(void) { return (int)reserved.GetCount(); }
	void ClearBudget(void) { reserved.Clear(); }

	void SetSettlingDay(int val){settleday = val;}
	int GetSettlingDay(void){return settleday;}
	void SetSettlingLastDay(bool flg){settlelastday = flg;}
	bool GetSettlingLastDay(void){return settlelastday;}
	void SetSettlingMonth(int val){settlemonth = val;}
	int GetSettlingMonth(void){return settlemonth;}
	void SetCurrencyUnit(const wxString &str){currencyunit = str;}
	const wxString &GetCurrencyUnit(void){return currencyunit;}
	void SetStartWeekDay(int val){startweekday = val;}
	int GetStartWeekDay(void){return startweekday;}
	void SetIconPath(const wxString &str){iconpath = str;}
	const wxString &GetIconPath(void){return iconpath;}
	void SetFontInfo(wxFont &ft){deffont = ft;}
	wxFont &GetFontInfo(void){return deffont;}

	int GetRecentCount(void) { return (int)recentfiles.GetCount(); }
	const wxString &GetRecent(int index) { return recentfiles.Item(index);  }
	void AddRecent(const wxString &file) { recentfiles.Add(file); }
	void SetRecent(int index, const wxString &file);
	void RemoveRecent(int index);
	void PushRecent(const wxString &file, bool enable_pop = false);
	void PopRecent(void);
	void ClearRecent(void) { recentfiles.Clear(); }

	void LoadDB(void);
	void WriteConfig(const wxString &name, const wxString &val);
	void WriteConfig(const wxString &name, int val);
	void WriteConfig(const wxString &name, bool val);
private:
	wxString username;
	wxString bookname;
	wxDateTime startdate;
	mon_int initialremainder;
	DBL_periodical period;
	DBL_holiday holiday;
	DBL_reserved reserved;
	int settleday;
	bool settlelastday;
	int settlemonth;
	wxString currencyunit;
	int startweekday;
	wxString iconpath;
	wxFont deffont;
	wxArrayString recentfiles;
	bool isencrypt;
};
class DB_kakeibo
{
public:
	DB_kakeibo(void);
	~DB_kakeibo(void) {}
	
	//executer SQL for each DB
	int AddBudget(DB_day db);
	int AddTotal(DB_total db);
	int AddExpense(DB_expense db);
	int AddItems(DB_items db);
	int AddAccount(DB_account db);
	int AddPeriod(DB_periodical db);
	int AddReserved(DB_reserved db);
	void SetBudget(DB_day cond, DB_day db);
	void SetExpense(int index, DB_expense db);
	void SetItems(DB_items cond, DB_items db);
	void SetAccount(int index, DB_account db);
	void SetTotal(DB_total cond, DB_total db);
	void SetPeriod(DB_periodical cond, DB_periodical db);
	void SetReserved(DB_reserved cond, DB_reserved db);
	vector<DB_day> GetContent(operatorType oper, DB_day cond1, DB_day cond2);
	DB_total GetTotal(DB_total cond);
	DB_total GetTotalNear(DB_total cond, wxString judge = _T("<"));
	DB_expense GetExpense(int id, int io);
	DB_items GetItems(int id, int expense);
	DB_account GetAccount(int id);
	
	int GetBudgetCount(DB_day db);
	int GetTotalCount(DB_total db);
	int GetLastIdOfBudget(const wxDateTime &date, int io, int handling);
	bool IsWorkDayExtra(const wxDateTime &date);
	int GetLastIdOfItems(int expense);
	wxArrayString GetStringDayTransaction(DB_day &db);
	
	int CountBudget;
	int CountTotal;
	int CountExpense;
	int CountItems;
	int CountAccount;
	DB_setting AppSetting;
private:
	vector<DB_day> dbday;
	vector<DB_total> dbtotal;
	vector<DB_expense> dbexpense;
	vector<DB_items> dbitems;
	vector<DB_account> dbaccount;
};
class DB_WeeklyReport
{
public:
	DB_WeeklyReport(void);
	void Clear(void);

	const wxString &GetExpenseName(void) { return expensename; }
	const wxString &GetItemName(void) { return itemname; }
	bool IsExistData(int index) { return isexist[index]; }
	wxDateTime GetItemDate(int index) { return itemdate[index]; }
	int GetAmount(int index) { return itemamount[index]; }
	InoutType GetIO(int index) { return itemio[index]; }


	void SetExpenseName(const wxString &expense);
	void SetItemName(const wxString &item);
	void SetData(int index, bool exist);
	void SetItemDate(int index, wxDateTime date);
	void SetAmount(int index, int amt);
	void SetIO(int index, InoutType io);

protected:
	wxString expensename;
	wxString itemname;
	bool isexist[5];
	wxDateTime itemdate[5];
	int itemamount[5];
	InoutType itemio[5];

};
WX_DECLARE_OBJARRAY(DB_WeeklyReport, DBL_WeeklyReport);

#endif